/*
v3.1.0 jQuery baigoValidate plugin 表单验证插件
(c) 2017 baigo studio - https://www.baigo.net/jquery/baigovalidate.html
License: http://www.opensource.org/licenses/mit-license.php
*/
;(function($) {
  $.fn.baigoValidate = function(options) {
    'use strict';
    if (this.length < 1) {
      return this;
    }

    var obj_form     = $(this);
    var form_data    = {};
    var message      = {};
    var err_count    = 0;
    var currentScene = '';

    var alias = {
      '>': 'gt',
      '>=': 'egt',
      '<': 'lt',
      '<=': 'elt',
      '=': 'eq',
      'same': 'eq',
      '!=': 'neq',
      '<>': 'neq'
    };

    var opts_default = {
      timeout: 30000,
      delimiter: ' - ',
      result_obj: {
        error_msg: 'error_msg',
        msg: 'msg'
      },
      type_msg: {
        require: '{:attr} require',
        confirm: '{:attr} out of accord with {:confirm}',
        different: '{:attr} cannot be same with {:different}',
        accepted: '{:attr} must be yes, on or 1',
        'in': '{:attr} must be in {:rule}',
        not_in: '{:attr} be notin {:rule}',
        between: '{:attr} must between {:rule}',
        not_between: '{:attr} cannot between {:rule}',
        length: 'Size of {:attr} must be {:rule}',
        min: 'Min size of {:attr} must be {:rule}',
        max: 'Max size of {:attr} must be {:rule}',
        after: '{:attr} cannot be less than {:rule}',
        before: '{:attr} cannot exceed {:rule}',
        expire: '{:attr} not within {:rule}',
        egt: '{:attr} must greater than or equal {:rule}',
        gt: '{:attr} must greater than {:rule}',
        elt: '{:attr} must less than or equal {:rule}',
        lt: '{:attr} must less than {:rule}',
        eq: '{:attr} must equal {:rule}',
        neq: '{:attr} cannot be same with {:rule}',
        regex: '{:attr} not conform to the rules',
        format: '{:attr} not conform format of {:rule}',
        date_format: '{:attr} must be date format of {:rule}',
        time_format: '{:attr} must be time format of {:rule}',
        date_time_format: '{:attr} must be datetime format of {:rule}',
        checkbox: 'Count of {:attr} must be {:rule}',
        radio: 'Count of {:attr} must be {:rule}',
        select: 'Count of {:attr} must be {:rule}',
        ajax: ''
      },
      format_msg: {
        number: '{:attr} must be numeric',
        'int': '{:attr} must be integer',
        'float': '{:attr} must be float',
        bool: '{:attr} must be bool',
        email: '{:attr} not a valid email address',
        date: '{:attr} not a valid date',
        time: '{:attr} not a valid time',
        date_time: '{:attr} not a valid datetime',
        alpha: '{:attr} must be alpha',
        alpha_number: '{:attr} must be alpha-numeric',
        alpha_dash: '{:attr} must be alpha-numeric, dash, underscore',
        chs: '{:attr} must be chinese',
        chs_alpha: '{:attr} must be chinese or alpha',
        chs_alpha_number: '{:attr} must be chinese, alpha-numeric',
        chs_dash: '{:attr} must be chinese, alpha-numeric, underscore, dash',
        url: '{:attr} not a valid url',
        ip: '{:attr} not a valid ip',
        ip_v4: '{:attr} not a valid ip',
        ip_v6: '{:attr} not a valid ip'
      },
      field_selector: {
        prefix_msg: '#msg_',
        prefix_group: '#group_'
      },
      class_name: {
        input: {
          success: 'is-valid',
          err: 'is-invalid'
        },
        msg: {
          success: 'valid-feedback',
          err: 'invalid-feedback',
          loading: 'text-info'
        },
        group: {
          success: 'text-success',
          err: 'text-danger'
        },
        attach: {
          success: 'text-success',
          err: 'text-danger'
        }
      },
      msg: {
        loading: 'Loading',
        ajax_err: 'Error'
      },
      box: {
        msg: 'Input error',
        selector: {
          box: '.bg-validate-box',
          msg: '.bg-msg'
        },
        tpl: '<div class="alert alert-danger alert-dismissible"><span class="bg-msg"></span><button type="button" class="close" data-dismiss="alert">&times;</button></div>',
        delay: 5000
      },
      extra: {
        class_name: 'bg-validate-extra',
        delay: 15000
      },
      extra_boxes: {},
      selector_types: {},
      rules: {},
      attr_names: {},
      scene: {},
      only: {},
      remove: {},
      append: {}
    };

    var opts = $.extend(true, opts_default, options);

    var _box_selector   = opts.box.selector;

    if ($(_box_selector.box).length < 1) {
      obj_form.append('<div class="bg-validate-box"></div>');
    }

    var process = {
      formatDate: function (fmt, time) { //author: meizz
        var _obj_date = new Date();
        _obj_date.setTime(time);

        var o = {
          'M+': _obj_date.getMonth() + 1, //月份
          'd+': _obj_date.getDate(), //日
          'H+': _obj_date.getHours(), //小时
          'm+': _obj_date.getMinutes(), //分
          's+': _obj_date.getSeconds(), //秒
          'q+': Math.floor((_obj_date.getMonth() + 3) / 3), //季度
          'S': _obj_date.getMilliseconds() //毫秒
        };

        if (/(y+)/.test(fmt)) {
          fmt = fmt.replace(RegExp.$1, (_obj_date.getFullYear() + '').substr(4 - RegExp.$1.length));
        }

        for (var k in o) {
          if (new RegExp('(' + k + ')').test(fmt)) {
            fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)));
          }
        }

        return fmt;
      },
      parseRule: function(arr_rule){
        //console.log(arr_rule);

        var _arr_ruleReturn = {};

        $.each(arr_rule, function(key, value){
          //console.log(key);

          if (typeof alias[key] != 'undefined') {
            key = alias[key];
          }

          if (typeof opts.type_msg[key] != 'undefined') {
            //console.log(value);

            switch (key) {
              case 'require':
                if (value === true || value === 'true') {
                  _arr_ruleReturn[key] = {
                    type: key,
                    rule: value
                  };
                }
              break;

              case 'length':
              case 'between':
              case 'not_between':
              case 'expire':
                if (value.indexOf(',') > 0) {
                  _arr_ruleReturn[key] = {
                    type: key,
                    rule: value
                  };
                }
              break;

              case 'min':
              case 'max':
              case 'in':
              case 'not_in':
              case 'egt':
              case 'gt':
              case 'elt':
              case 'lt':
              case 'eq':
              case 'neq':
              case 'before':
              case 'after':
              case 'regex':
                if (value != null) {
                  _arr_ruleReturn[key] = {
                    type: key,
                    rule: value
                  };
                }
              break;

              case 'date_format':
              case 'time_format':
              case 'date_time_format':
                var _str_format = process.getDateRule(key);

                if (value != null) {
                  _str_format = value;
                }

                _arr_ruleReturn[key] = {
                  type: key,
                  rule: _str_format
                };
              break;

              case 'format':
                //console.log(opts.format_msg[value]);
                if (typeof opts.format_msg[value] != 'undefined') {
                  _arr_ruleReturn[key] = {
                    type: key,
                    rule: value
                  };

                  //console.log(value);
                }
              break;

              case 'ajax':
                if (typeof value.url != 'undefined') {
                  _arr_ruleReturn[key] = {
                    type: key,
                    rule: value
                  };

                  //console.log(value);
                }
              break;

              default:
                var _rule;

                if (typeof value == 'string') {
                  _rule = value;
                } else {
                  _rule = null;
                }

                _arr_ruleReturn[key] = {
                  type: key,
                  rule: _rule
                };

                //console.log(key);
                //console.log(_arr_ruleReturn[key]);
              break;
            }

            //console.log(key);
          }
        });

        //console.log(_arr_ruleReturn);

        return _arr_ruleReturn;
      },
      getDateRule: function(type){
        var _str_format = '';

        switch (type) {
          case 'date_format':
            _str_format = 'yyyy-MM-dd';
          break;

          case 'time_format':
            _str_format = 'H:i:s';
          break;

          case 'date_time_format':
            _str_format = 'yyyy-MM-dd H:i:s';
          break;
        }

        return _str_format;
      },
      check: function(str_value, arr_rule, str_key) {
        //var err_count = 0;

        //console.log(arr_rule);

        if (typeof arr_rule == 'object') {
          var _arr_rule  = process.parseRule(arr_rule);
          var _err_count = 0;

          $.each(_arr_rule, function(_key_item, _value_item){
            if (typeof _value_item.type != 'undefined' && typeof _value_item.rule != 'undefined') {
              if (!process.checkItem(str_value, _value_item, str_key)) {
                err_count++;
                _err_count++;
              }
            }
          });
        }

        //console.log(err_count);

        if (_err_count > 0) {
          //console.log(str_key);
          //console.log(_str_msg);

          if (typeof message[str_key] != 'undefined') {
            var _str_msg = message[str_key];
          }

          process.output(str_key, _str_msg, 'err');
        } else {
          process.output(str_key, '', 'success');
        }

        //return err_count;
      },
      checkItem: function(str_value, arr_rule, str_key) {
        var _bool_return = false;
        var _obj_reg;

        switch (arr_rule.type) {
          case 'require':
            _bool_return = el.min(str_value, 1);
          break;

          case 'length':
            _bool_return = el.leng(str_value, arr_rule.rule);
          break;

          case 'between':
          case 'not_between':
          case 'expire':
          case 'in':
          case 'not_in':
          case 'egt':
          case 'gt':
          case 'elt':
          case 'lt':
          case 'eq':
          case 'neq':
          case 'before':
          case 'after':
          case 'regex':
          case 'min':
          case 'max':
            _bool_return = el[process.toHump(arr_rule.type)](str_value, arr_rule.rule);
          break;

          case 'bool':
            var _array   = [true, 'true', 0, 1, '0', '1'];
            _bool_return = process.inArray(str_value, _array);
          break;

          case 'accepted':
            var _array   = ['1', 'on', 'yes'];
            _bool_return = process.inArray(str_value, _array);
          break;

          case 'date_format':
          case 'time_format':
          case 'date_time_format':
            _bool_return = el.dateFormat(str_value, arr_rule.rule);
          break;

          case 'confirm':
            if (typeof arr_rule.rule == 'string') {
              arr_rule.rule = arr_rule.rule;
            } else {
              arr_rule.rule = str_key.replace('_confirm', '');
            }

            //console.log(arr_rule.rule);

            _bool_return = el.confirm(str_value, arr_rule.rule);
          break;


          case 'different':
            if (typeof arr_rule.rule == 'string') {
              arr_rule.rule = arr_rule.rule;
            } else {
              arr_rule.rule = str_key.replace('_different', '');
            }

            _bool_return = el.confirm(str_value, arr_rule.rule, true);
          break;

          case 'ajax':
            el.ajaxCheck(str_value, str_key, arr_rule.rule);
            _bool_return = true;
          break;

          case 'checkbox':
          case 'radio':
            //console.log(arr_rule);
            _bool_return = el.checkForm(str_key, arr_rule.rule);
          break;

          case 'select':
            _bool_return = el.selectForm(str_key, arr_rule.rule);
          break;

          case 'format':
            switch (arr_rule.rule) {
              case 'date':
              case 'time':
              case 'date_time':
                var _value = str_value.replace(/-/g, '/');

                if (!isNaN(Date.parse(_value))) {
                  _bool_return = true;
                }
              break;

              case 'alpha':
                _obj_reg = /^[A-Za-z]+$/;
                _bool_return = el.regex(str_value, _obj_reg);
              break;

              case 'alpha_number':
                _obj_reg = /^[A-Za-z0-9]+$/;
                _bool_return = el.regex(str_value, _obj_reg);
              break;

              case 'alpha_dash':
                // 只允许字母、数字和下划线 破折号
                _obj_reg = /^[A-Za-z0-9_\-]+$/;
                _bool_return = el.regex(str_value, _obj_reg);
              break;

              case 'chs':
                // 只允许汉字
                _obj_reg = /^[\u4e00-\u9fa5]+$/;
                _bool_return = el.regex(str_value, _obj_reg);
              break;

              case 'chs_alpha':
                // 只允许汉字、字母
                _obj_reg = /^[\u4e00-\u9fa5A-Za-z]+$/;
                _bool_return = el.regex(str_value, _obj_reg);
              break;

              case 'chs_alpha_number':
                // 只允许汉字、字母和数字
                _obj_reg = /^[\u4e00-\u9fa5A-Za-z0-9]+$/;
                _bool_return = el.regex(str_value, _obj_reg);
              break;

              case 'chs_dash':
                // 只允许汉字、字母、数字和下划线_及破折号-
                _obj_reg = /^[\u4e00-\u9fa5A-Za-z0-9\_\-]+$/;
                _bool_return = el.regex(str_value, _obj_reg);
              break;

              case 'number':
                _bool_return = process.isNumber(str_value);
              break;

              case 'int':
                _obj_reg = /^[\+\-]?[0-9]+$/;
                _bool_return = el.regex(str_value, _obj_reg);
              break;

              case 'float':
                _obj_reg = /^[\+\-]?[0-9]+\.[0-9]+$/;
                _bool_return = el.regex(str_value, _obj_reg);
              break;

              case 'email':
                _obj_reg = /^([A-Za-z0-9][\.\_\-]?)+\@([A-Za-z0-9][\.\-]?)+[A-Za-z]{2,4}$/;
                _bool_return = el.regex(str_value, _obj_reg);
              break;

              case 'ip':
              case 'ip_v4':
                // 是否为IP地址
                _obj_reg = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
                _bool_return = el.regex(str_value, _obj_reg);
              break;

              case 'ip_v6':
                // 是否为IPV6地址
                _obj_reg = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/;
                _bool_return = el.regex(str_value, _obj_reg);
              break;

              case 'url':
                // 是否为一个URL地址
                _obj_reg = /^((https?|ftp|file):)?\/\/[\-A-Za-z0-9+&@#\/%?\=~\_|!:,\.;]+[\-A-Za-z0-9+&@#\/%\=~\_|]$/;
                _bool_return = el.regex(str_value, _obj_reg);
              break;
            }
          break;
        }

        //console.log(str_key);
        //console.log(_bool_return);

        if (!_bool_return) {
          var _str_msg        = 'unknown';
          var _str_field      = str_key;
          var _str_confirm    = str_key;
          var _str_different  = str_key;

          //console.log(arr_rule.type);

          if (arr_rule.type == 'format') {
            if (typeof opts.format_msg[arr_rule.rule] != 'undefined') {
              _str_msg = opts.format_msg[arr_rule.rule];
            }
          } else {
            if (typeof opts.type_msg[arr_rule.type] != 'undefined') {
              _str_msg = opts.type_msg[arr_rule.type];
            }
          }

          if (typeof opts.attr_names[str_key] != 'undefined') {
            _str_field = opts.attr_names[str_key];
          }

          if (typeof opts.attr_names[arr_rule.rule] != 'undefined') {
            _str_confirm   = opts.attr_names[arr_rule.rule];
            _str_different = opts.attr_names[arr_rule.rule];
          }

          switch (arr_rule.type) {
            case 'length':
            case 'between':
            case 'not_between':
              arr_rule.rule = arr_rule.rule.replace(',', opts.delimiter);
            break;
          }

          _str_msg = _str_msg.replace('{:attr}', _str_field);
          _str_msg = _str_msg.replace('{:rule}', arr_rule.rule);
          _str_msg = _str_msg.replace('{:confirm}', _str_confirm);
          _str_msg = _str_msg.replace('{:different}', _str_different);

          message[str_key] = _str_msg;

          //console.log(str_key);
          //console.log(_str_msg);
        }

        return _bool_return;
      },
      getLeng: function(str_value) {
        var _numLenth  = 0;
        if (typeof str_value != 'undefined') {
          for (var _iii = 0; _iii < str_value.length; _iii++) {
            var _chkCode = str_value.charCodeAt(_iii);
            if (_chkCode < 0x007f) {
              _numLenth++;
            } else if (_chkCode <= 0x07ff) {
              _numLenth += 2;
            } else if (_chkCode <= 0xffff) {
              _numLenth += 3;
            } else{
              _numLenth += 4;
            }
          }
        }
        return _numLenth;
      },
      isNumber: function(str_value) {
        if (str_value.length < 1) {
          return true;
        }

        str_value = Number(str_value);

        //console.log(str_value);

        if (typeof str_value == 'number' && !isNaN(str_value)) {
          return true;
        } else {
          return false;
        }
      },
      inArray: function(str_value, arr_rule) {
        if (str_value.length < 1) {
          return true;
        }

        if (arr_rule.rule.indexOf(str_value) >= 0) {
          return true;
        } else {
          return false;
        }
      },
      output: function(key, msg, status) {
        //console.log(_type);

        var _selector   = process.getSelector(key);

        $(opts.field_selector.prefix_msg + key).text(msg); //填充消息

        $(_selector).removeClass(opts.class_name.input.success + ' ' + opts.class_name.input.err);
        $(opts.field_selector.prefix_msg + key).removeClass(opts.class_name.msg.success + ' ' + opts.class_name.msg.err + ' ' + opts.class_name.msg.loading);
        $(opts.field_selector.prefix_group + key).removeClass(opts.class_name.group.success + ' ' + opts.class_name.group.err);
        $(opts.field_selector.prefix_group + key).removeClass(opts.class_name.attach.success + ' ' + opts.class_name.attach.err);

        if (typeof opts.class_name.input[status] != 'undefined') {
          $(_selector + ':not(select,:radio:not(:checked),:checkbox:not(:checked))').addClass(opts.class_name.input[status]);
        }

        if (typeof opts.class_name.msg[status] != 'undefined') {
          $(opts.field_selector.prefix_msg + key).addClass(opts.class_name.msg[status]);
        }

        $(opts.field_selector.prefix_msg + key).show(); //显示消息

        if (typeof opts.class_name.group[status]) {
          $(opts.field_selector.prefix_group + key).addClass(opts.class_name.group[status]);
        } else if (typeof opts.class_name.attach[status]) {
          $(opts.field_selector.prefix_group + key).addClass(opts.class_name.attach[status]);
        }

        if (typeof opts.extra_boxes[key] != 'undefined') {
          var _extra_box = opts.extra_boxes[key];

          if (typeof _extra_box == 'object') {
            if (typeof _extra_box.selector != 'undefined') {
              process.extraOutput(status, _extra_box.selector, _extra_box.msg);
            }
          } else if (typeof _extra_box == 'string') {
            process.extraOutput(status, _extra_box);
          }
        }
      },
      boxOutput: function() {
        if (err_count > 0) {
          $(_box_selector.box).html(opts.box.tpl);

          if (typeof opts.box.msg != 'undefined' && opts.box.msg.length > 0) {
            $(_box_selector.box + ' ' + _box_selector.msg).text(opts.box.msg); //填充消息
          }

          $(_box_selector.box).slideDown(function(){
            setTimeout(function(){
                $(_box_selector.box).slideUp();
            }, opts.box.delay);
          });
        } else {
          $(_box_selector.box).slideUp();
        }
      },
      extraOutput: function(status, selector, msg) {
        console.log(msg);
        var _obj_extra = $(selector);

        if (_obj_extra.length > 0) {
          if (status == 'err') {
            _obj_extra.addClass(opts.extra.class_name);

            if (typeof msg != 'undefined' && msg.length > 0) {
              _obj_extra.text(msg); //填充消息
            }

            _obj_extra.show();
          } else {
            if (err_count < 1) {
              _obj_extra.hide();
            }
          }
        }
      },
      getSelector: function(key) {
        var _selector = '';
        var _type;

        if (typeof opts.selector_types[key] == 'undefined') {
          _type = 'id';
        } else {
          _type = opts.selector_types[key];
        }

        //console.log(selector_type);

        switch (_type) {
          case 'validate':
            _selector = '[data-validate=' + key + ']';
          break;

          case 'name':
            _selector = '[name=' + key + ']';
          break;

          case 'class':
            _selector = '.' + key;
          break;

          default:
            _selector = '#' + key;
          break;
        }

        return _selector;
      },
      getRule: function() {
        var _arr_rule = {};

        if (currentScene.length > 0 && typeof opts.scene[currentScene] == 'object' && opts.scene[currentScene].length > 0) { // 如果规定场景
          $.each(opts.scene[currentScene], function(_key, _value) { // 遍历当前场景下的规则
            if (process.isNumber(_key)) {
              if (typeof opts.rules[_value] != 'undefined') {
                _arr_rule[_value] = opts.rules[_value];
              }
            } else {
              if (typeof opts.rules[_key] != 'undefined') {
                _arr_rule[_key] = opts.rules[_key];
              } else if (typeof _value == 'object') {
                _arr_rule[_key] = _value;
              }
            }
          });
        } else {
          _arr_rule = opts.rules;
        }

        if (opts.only.length > 0) { // 如果规定了仅验证规则, 则取出匹配的规则
          var _arr_only = {};

          $.each(opts.only, function(_key, _value) {
            if (typeof _arr_rule[_value] != 'undefined') {
              _arr_only[_value] = _arr_rule[_value];
            }
          });

          if (_arr_only.length > 0) {
            _arr_rule = _arr_only;
          }
        } else if (opts.remove.length > 0) { // 移除规则
          $.each(opts.remove, function(_key, _value) {
            if (typeof _arr_rule[_value] != 'undefined') {
              delete _arr_rule[_value];
            }
          });
        } else if (opts.append.length > 0) { // 追加规则
          $.each(opts.append, function(_key, _value) {
            if (typeof _arr_rule[_key] != 'undefined') {
              _arr_rule[_key] = _value;
            }
          });
        }

        return _arr_rule;
      },
      getData: function() {
        form_data = {};
        err_count = 0;
        var _arr_data = {};

        var _arr_serialize = obj_form.serializeArray();

        $.each(_arr_serialize, function(i, field){
          //console.log(field.value);
          _arr_data[field.name] = field.value;
        });

        $.each(opts.rules, function(key, value){
          if (typeof _arr_data[key] != 'undefined') {
            form_data[key] = _arr_data[key];
          } else {
            var _selector  = process.getSelector(key);

            form_data[key] = $(_selector).val();
          }
        });

        //console.log(form_data);
      },
      toHump: function(str) { // 下划线转换驼峰
        return str.replace(/\_(\w)/g, function(all, letter){
          return letter.toUpperCase();
        });
      },
      toLine: function(str) { // 驼峰转换下划线
        return str.replace(/([A-Z])/g, '_$1').toLowerCase();
      }
    };

    var el = {
      verify: function(field){
        process.getData();
        var _status   = true;
        var _err      = '';
        var _arr_rule = process.getRule(); // 获取规则

        //console.log(form_data);

        if (typeof field == 'undefined') {
          $.each(_arr_rule, function(key, value){
            if (typeof value != 'undefined') {
              if (typeof form_data[key] == 'undefined') {
                form_data[key] = '';
              }
              process.check(form_data[key], value, key);
            }
          });

          if (err_count > 0) {
            _status = false;
          }

          process.boxOutput();
        } else {
          if (typeof _arr_rule[field] != 'undefined') {
            process.check(form_data[field], _arr_rule[field], field);
          }
        }

        //console.log(err_count);

        return _status;
      },
      setRules: function(rules) {
        opts.rules = rules;
      },
      leng: function(value, rule){
        var _status   = true;
        var _arr_rule = [];

        if (rule.indexOf(',') > 0) {
          _arr_rule = rule.split(',');
        } else {
          _arr_rule[0] = rule;
          _arr_rule[1] = 0;
        }

        //console.log(process.getLeng(value));

        var _min = _arr_rule[0];
        var _max = _arr_rule[1];

        if (_min > 0 && process.getLeng(value) < _min) {
          _status = false; //如果定义最小长度，且短于，则返回太短
        } else if (_max > 0 && process.getLeng(value) > _max) {
          _status = false; //如果定义最大长度，且长于，则返回太长
        }

        return _status;
      },
      checkForm: function(key, rule){
        var _selector = process.getSelector(key);

        var _status   = true;
        var _arr_rule = [];

        if (rule.indexOf(',') > 0) {
          _arr_rule = rule.split(',');
        } else {
          _arr_rule[0] = rule;
          _arr_rule[1] = 0;
        }

        //console.log(value.length);

        var _min = _arr_rule[0];
        var _max = _arr_rule[1];

        if (_min > 0 && $(_selector + ':checked').length < _min) {
          _status = false; //如果定义最小长度，且短于，则返回太短
        } else if (_max > 0 && $(_selector + ':checked').length > _max) {
          _status = false; //如果定义最大长度，且长于，则返回太长
        }

        return _status;
      },
      selectForm: function(key, rule){
        var _selector = process.getSelector(str_key);

        var _status   = true;
        var _arr_rule = [];

        if (rule.indexOf(',') > 0) {
          _arr_rule = rule.split(',');
        } else {
          _arr_rule[0] = rule;
          _arr_rule[1] = 0;
        }

        //console.log(value.length);

        var _min = _arr_rule[0];
        var _max = _arr_rule[1];

        if (_min > 0 && $(_selector + ' option:selected').length < _min) {
          _status = false; //如果定义最小长度，且短于，则返回太短
        } else if (_max > 0 && $(_selector + ' option:selected').length > _max) {
          _status = false; //如果定义最大长度，且长于，则返回太长
        }

        return _status;
      },
      min: function(value, rule){
        var _status   = true;

        if (rule > 0 && process.getLeng(value) < rule) {
          _status = false; //如果定义最小长度，且短于，则返回太短
        }

        return _status;
      },
      max: function(value, rule){
        var _status   = true;

        if (rule > 0 && process.getLeng(value) > rule) {
          _status = false; //如果定义最大长度，且长于，则返回太长
        }

        return _status;
      },
      dateFormat: function(value, rule){
        if (value.length < 1) {
          return true;
        }

        var _value = value.replace(/-/g, '/');
        var _time  = Date.parse(value);
        var _str   = process.formatDate(_time);

        //console.log('jisuan: ' + _str);

        return _str == value;
      },
      regex: function(value, rule) {
        if (value.length < 1) {
          return true;
        }

        var _obj_rule;

        if (typeof rule == 'object') {
          _obj_rule = rule;
        } else {
          if (rule.indexOf('^') < 0) {
            rule = '^' + rule;
          }
          if (rule.indexOf('$') < 0) {
            rule = rule + '$';
          }

          //console.log(rule);

          _obj_rule = new RegExp(rule);
        }

        var _obj_keys = Object.keys(_obj_rule);

        //console.log(_obj_rule);

        return _obj_rule.test(value);
      },
      expire: function(value, rule) {
        if (value.length < 1) {
          return true;
        }

        var _arr_rule = rule.split(',');
        var _obj_date = new Date();
        var _now      = _obj_date.getTime()

        var start   = _arr_rule[0];
        var end     = _arr_rule[1];

        if (process.isNumber(start)) {
          start = Date.parse(start);
        }

        if (process.isNumber(end)) {
          end = Date.parse(end);
        }

        return _now >= start && _now <= end;
      },
      after: function(value, rule) {
        if (value.length < 1) {
          return true;
        }

        if (process.isNumber(value)) {
          value = Date.parse(value);
        }

        if (process.isNumber(rule)) {
          rule = Date.parse(rule);
        }

        return value >= rule;
      },
      before: function(value, rule) {
        if (value.length < 1) {
          return true;
        }

        if (process.isNumber(value)) {
          value = Date.parse(value);
        }

        if (process.isNumber(rule)) {
          rule = Date.parse(rule);
        }

        return value <= rule;
      },
      'in': function(value, rule) {
        if (value.length < 1) {
          return true;
        }

        var _arr_rule = [];

        if (rule.indexOf(',') > 0) {
          _arr_rule = rule.split(',');
        } else {
          _arr_rule[0] = rule;
        }

        return process.inArray(value, _arr_rule);
      },
      notIn: function(value, rule) {
        if (value.length < 1) {
          return true;
        }

        var _arr_rule = [];

        if (rule.indexOf(',') > 0) {
          _arr_rule = rule.split(',');
        } else {
          _arr_rule[0] = rule;
        }

        return !process.inArray(value, _arr_rule);
      },
      between: function(value, rule) {
        if (value.length < 1) {
          return true;
        }

        var _arr_rule = rule.split(',');

        var min   = Number(_arr_rule[0]);
        var max   = Number(_arr_rule[1]);
        value = Number(value);

        return value >= min && value <= max;
      },
      notBetween: function(value, rule) {
        if (value.length < 1) {
          return true;
        }

        var _arr_rule = rule.split(',');

        var min   = Number(_arr_rule[0]);
        var max   = Number(_arr_rule[1]);
        value = Number(value);

        return value < min || value > max;
      },
      egt: function(value, rule) {
        if (value.length < 1) {
          return true;
        }

        value = Number(value);
        rule  = Number(rule);

        return value >= rule;
      },
      gt: function(value, rule) {
        if (value.length < 1) {
          return true;
        }

        value = Number(value);
        rule  = Number(rule);

        return value > rule;
      },
      elt: function(value, rule) {
        if (value.length < 1) {
          return true;
        }

        value = Number(value);
        rule  = Number(rule);

        return value <= rule;
      },
      lt: function(value, rule) {
        if (value.length < 1) {
          return true;
        }

        value = Number(value);
        rule  = Number(rule);

        return value < rule;
      },
      eq: function(value, rule) {
        if (value.length < 1) {
          return true;
        }

        return value == rule;
      },
      neq: function(value, rule) {
        if (value.length < 1) {
          return true;
        }

        return value != rule;
      },
      scene: function(sceneName) {
        currentScene = sceneName;
      },
      getMessage: function(){
        return message;
      },
      confirm: function(value, rule, is_different){
        if (typeof is_different != 'undefined' && is_different === true) {
          return form_data[rule] != value;
        } else {
          return form_data[rule] == value;
        }
      },
      ajaxCheck: function(value, key, rule){
        //console.log(error[key]);

        if (value.length < 1) {
          return;
        }

        //console.log(err_count);

        if (err_count > 0) {
          return;
        }

        var _str_key;

        if (typeof rule.key != 'undefined') {
          _str_key = rule.key;
        } else {
          _str_key = key;
        }

        var _ajaxData = _str_key + '=' + value;

        if (typeof rule.attach != 'undefined') {
          if (typeof rule.attach.selectors != 'undefined' && typeof rule.attach.keys != 'undefined') {
            $.each(rule.attach.selectors, function(index, _selector) {
              if (typeof rule.attach.keys[index] != 'undefined') {
                _ajaxData += '&' + rule.attach.keys[index] + '=' + $(_selector).val();
              }
            });
          }
        }

        _ajaxData += '&' + new Date().getTime() + 'at' + Math.random();

        $.ajax({
          url: rule.url, //url
          //async: false, //设置为同步
          dataType: 'json', //数据格式为json
          data: _ajaxData,
          timeout: opts.timeout,
          beforeSend: function(){
            process.output(key, opts.msg.loading, 'loading');
          },
          error: function(result){
            //console.log(result);
            process.output(key, opts.msg.ajax_err + '! ' + result.status + ' ' + result.statusText, 'err');
          },
          success: function(result) { //读取返回结果
            //console.log(result);
            if (typeof result[opts.result_obj.error_msg] != 'undefined') {
              process.output(key, result[opts.result_obj.error_msg], 'err');
            } else if (typeof result[opts.result_obj.msg] != 'undefined') {
              process.output(key, result[opts.result_obj.msg], 'success');
            }
          }
        });
      }
    };

    obj_form.find('*').change(function(){
      var _input_key  = '';
      var _input_tag  = $(this).prop('tagName');

      if (typeof _input_tag != 'undefined') {
        _input_tag = _input_tag.toLowerCase();
      } else {
        _input_tag = 'input';
      }

      var _validate   = $(this).data('validate');
      var _id         = $(this).attr('id');
      var _name       = $(this).attr('name');
      var _class      = $(this).attr('class');

      //console.log(_input_tag);

      switch (_input_tag) {
        case 'select':
        case 'textarea':
          if (typeof _validate != 'undefined' && _validate.length > 0) {
            _input_key   = _validate;
          } else if (typeof _id != 'undefined' && _id.length > 0) {
            _input_key   = _id;
          } else if (typeof _name != 'undefined' && _name.length > 0) {
            _input_key   = _name;
          }
        break;

        default:
          var _input_type = $(this).attr('type');

          if (typeof _input_type == 'undefined') {
            _input_type = 'text';
          }

          _input_type = _input_type.toLowerCase();

          //console.log(_input_type);

          switch (_input_type) {
            case 'checkbox':
            case 'radio':
              if (typeof _validate != 'undefined' && _validate.length > 0) {
                _input_key   = _validate;
              } else if (typeof _name != 'undefined' && _name.length > 0) {
                _input_key   = _name;
              } else if (typeof _class != 'undefined' && _class.length > 0) {
                _input_key   = _class;
              }
            break;

            default:
              //console.log(_name);

              if (typeof _validate != 'undefined' && _validate.length > 0) {
                _input_key   = _validate;
              } else if (typeof _id != 'undefined' && _id.length > 0) {
                _input_key   = _id;
              } else if (typeof _name != 'undefined' && _name.length > 0) {
                _input_key   = _name;
              }
            break;
          }
        break;
      }

      //console.log(_input_key);

      el.verify(_input_key);
    });

    return el;
  };
})(jQuery);
